﻿#include "ssTime.h"
#ifdef SS_USE_WINDOWS
#include <Windows.h>
#endif
#include "../string/ssStrfunc.h"


namespace StarSeeker
{
	time_t ssTime::s_sysStart = (u32)::time(NULL);
	i32 ssTime::s_timeZone = 8;
	time_t ssTime::s_todayZero = 0;

void ssYMDHMS::Zero()
{
	year.i32p = month.i32p = day.i32p = hour.i32p = minute.i32p = second.i32p = wday.i32p = yday.i32p = 0;
}

void ssYMDHMS::GetLocalTime(char* buf)
{
	snprintf(buf, SS_TIME_STR_LEN, "%d-%d-%d %d:%d:%d", year.i32p, month.i32p, day.i32p, minute.i32p, second.i32p, second.i32p);
}

ST64_u ssTime::GetTimeNow()
{
	ST64_u t;
	t.i64p = ::time(0);
	return t;
}

ST64_u ssTime::GetTimeNowMS()
{
	ST64_u t;
#ifdef SS_USE_WINDOWS
	static u64 timeStamp = 0;
	if (timeStamp <= 0)
	{
		timeStamp = (time(NULL) - GetTickCount() / 1000) * 1000;
	}
	t.u64p = timeStamp + GetTickCount();
#else
	struct timeval tv;
	gettimeofday(&tv, NULL);
	t.i64p = tv.tv_sec * 1000;
	t.i64p += tv.tv_usec / 1000;
#endif
	return t;
}

tm* ssTime::GetTime()
{
	time_t now = ::time(NULL);
	return ::gmtime(&now);
}

tm* ssTime::GetTime(time_t timestamp)
{
	return ::gmtime(&timestamp);
}

void ssTime::GetTime(ssYMDHMS& t)
{
	tm* ti = GetTime();
	t.year.i32p = ti->tm_year + 1900;
	t.month.i32p = ti->tm_mon + 1;
	t.day.i32p = ti->tm_mday;
	t.hour.i32p = ti->tm_hour;
	t.minute.i32p = ti->tm_min;
	t.second.i32p = ti->tm_sec;
	t.wday.i32p = ti->tm_wday;
	t.yday.i32p = ti->tm_yday;
}

void ssTime::GetTime(time_t timestamp, ssYMDHMS& out)
{
	tm* ti = gmtime(&timestamp);
	out.year.i32p = ti->tm_year + 1900;
	out.month.i32p = ti->tm_mon + 1;
	out.day.i32p = ti->tm_mday;
	out.hour.i32p = ti->tm_hour;
	out.minute.i32p = ti->tm_min;
	out.second.i32p = ti->tm_sec;
	out.wday.i32p = ti->tm_wday;
	out.yday.i32p = ti->tm_yday;
}

time_t ssTime::GetTimestamp(ssYMDHMS& t)
{
	tm t2 = { 0 };
	t2.tm_year = t.year.i32p-1900;
	t2.tm_mon = t.month.i32p - 1;
	t2.tm_mday = t.day.i32p;
	t2.tm_hour = t.hour.i32p;
	t2.tm_min = t.minute.i32p;
	t2.tm_sec = t.second.i32p;
	return ::mktime(&t2);
}

void ssTime::GetLocalTime(char* buf)
{
	tm* ti = GetLocalTime();
	snprintf(buf, SS_TIME_STR_LEN, "%d-%d-%d %d:%d:%d", ti->tm_year + 1900, ti->tm_mon + 1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec);
}

tm* ssTime::GetLocalTime()
{
	time_t now = ::time(NULL) + ssTime::s_timeZone * 3600;
	return ::gmtime(&now);
}

tm * ssTime::GetLocalTime(time_t timestamp)
{
	timestamp += ssTime::s_timeZone * 3600;
	return ::gmtime(&timestamp);
}

void ssTime::GetLocalTime(ssYMDHMS& t)
{
	tm* ti = GetLocalTime();
	t.year.i32p = ti->tm_year + 1900;
	t.month.i32p = ti->tm_mon + 1;
	t.day.i32p = ti->tm_mday;
	t.hour.i32p = ti->tm_hour;
	t.minute.i32p = ti->tm_min;
	t.second.i32p = ti->tm_sec;
	t.wday.i32p = ti->tm_wday;
	t.yday.i32p = ti->tm_yday;
}

void ssTime::GetLocalTime(time_t timestamp, ssYMDHMS& out)
{
	timestamp += ssTime::s_timeZone*3600;
	tm* ti = gmtime(&timestamp);
	out.year.i32p = ti->tm_year+1900;
	out.month.i32p = ti->tm_mon+1;
	out.day.i32p = ti->tm_mday;
	out.hour.i32p = ti->tm_hour;
	out.minute.i32p = ti->tm_min;
	out.second.i32p = ti->tm_sec;
	out.wday.i32p = ti->tm_wday;
	out.yday.i32p = ti->tm_yday;
}

time_t ssTime::GetLocalTimestamp(ssYMDHMS& t)
{
	return GetTimestamp(t) + ssTime::s_timeZone * 3600;
}

void ssTime::GetLocalTimeYMD( char* buf )
{
	tm* ti = GetLocalTime();
	snprintf(buf, SS_TIME_STR_LEN, "%d-%d-%d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday);
}

void ssTime::GetLocalTimeYMDH( char* buf )
{
	tm* ti = GetLocalTime();
	snprintf(buf, SS_TIME_STR_LEN, "%d-%d-%d.%d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour);
}

void ssTime::GetLocalTimeHMS( char* buf )
{
	tm* ti = GetLocalTime();
	snprintf(buf, SS_TIME_STR_LEN, "%d:%d:%d",ti->tm_hour,ti->tm_min,ti->tm_sec);
}

ST32_u ssTime::GetDateNum(bool localTime)
{
	tm* ti = localTime?GetLocalTime():GetTime();
	ST32_u n;
	n.i32p = (ti->tm_year+1900)*10000 + (ti->tm_mon+1)*100 + ti->tm_mday;
	return n;
}

ST32_u ssTime::GetTimeNum(bool localTime)
{
	tm* ti = localTime ? GetLocalTime() : GetTime();
	ST32_u n;
	n.i32p = ti->tm_hour * 10000 + ti->tm_min * 100 + ti->tm_sec;
	return n;
}

void ssTime::SetTimeZone( i32 zone )
{
	ssTime::s_timeZone = zone;
}

ST64_u ssTime::GetDayZero(time_t timestamp)
{
	ST64_u dayZero;
	dayZero.i64p = timestamp - timestamp % 86400 - ssTime::s_timeZone * 3600;
	return dayZero;
}

ST64_u ssTime::GetTodayZero()
{
	time_t now = ::time(NULL);
	if (now - ssTime::s_todayZero > 86400)
	{
		ssTime::s_todayZero = now - now % 86400 - ssTime::s_timeZone * 3600;
		if (ssTime::s_todayZero + 86400 <= now)
		{
			ssTime::s_todayZero += 86400;
		}
	}
	ST64_u ret;
	ret.i64p = ssTime::s_todayZero;
	return ret;
}

StarSeeker::i32 ssTime::GetDayDiff(time_t timestamp1, time_t timestamp2)
{
	ST64_u d1 = GetDayZero(timestamp1);
	ST64_u d2 = GetDayZero(timestamp2);
	return i32(d2.i64p - d1.i64p);
}

time_t ssTime::GetStart()
{
	return s_sysStart;
}

}
